package in.iqing.module.content;

import android.content.Context;
import android.graphics.Paint;
import android.os.AsyncTask;
import android.os.Handler;
import android.os.Message;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;

import java.util.ArrayList;
import java.util.List;

import in.iqing.app.R;
import in.iqing.control.helper.LogHelper;
import in.iqing.control.util.ConvertUtil;
import in.iqing.control.util.MiscUtil;
import in.iqing.control.util.UnitUtil;
import in.iqing.model.bean.Chapter;
import in.iqing.model.bean.Page;
import in.iqing.model.bean.Paragraph;
import in.iqing.model.sp.SettingSP;

/**
 * Created by neavo on 2015/1/7.
 */

public class QingPageContainer extends FrameLayout implements Handler.Callback {
    private static final String TAG = "QingPageContainer";

    private int width;
    private int height;
    private int lineNum;
    private int lineSpace;
    private int charHeight;
    private boolean traditional;

    private Paint charPaint;
    private Chapter chapter;
    private List<Page> pages;

    private float downX;
    private float thresholdX;
    private GestureDetector gestureDetector;

    private Handler handler;
    private ICallback callback;
    private static final int WHAT_PREPARED = 0x0001;

    private ViewPager bookPager;
    private BookPagerAdapter pagerAdapter;
    private boolean enableScrolling;

    public interface ICallback {

        void onPrepared();

        void onPageChanged();

        void onPrevClick();

        void onNextClick();

        void onCenterClick();
    }

    public QingPageContainer(Context context) {
        super(context);
        onInitialize();
    }

    public QingPageContainer(Context context, AttributeSet attrs) {
        super(context, attrs);
        onInitialize();
    }


    @Override
    public boolean handleMessage(Message msg) {
        boolean isConsumed = false;

        switch (msg.what) {
            case WHAT_PREPARED:
                isConsumed = true;
                processWhatPrepared();
                break;
        }

        return isConsumed;
    }

    public void onInitialize() {
        initVariables();
    }

    private void initVariables() {
        this.handler = new Handler(this);
        this.gestureDetector = new GestureDetector(getContext(), new GestureDetectorSimpleOnGestureListener());
        this.thresholdX = UnitUtil.toPx(getContext(), 48);
        this.width = MiscUtil.getScreenWidth(getContext()) - UnitUtil.toPx(getContext(), 16);
        this.height = MiscUtil.getScreenHeight(getContext()) - UnitUtil.toPx(getContext(), 22);
        this.lineSpace = UnitUtil.toPx(getContext(), SettingSP.getSingleton(getContext()).getSpace());
        enableScrolling = true;
        this.charPaint = new Paint();
        charPaint.setAntiAlias(true);
    }

    private void setupTraditional() {
        this.traditional = SettingSP.getSingleton(getContext()).getTraditional();
    }

    private void setupPager() {
        charPaint.setColor(getContext().getResources().getColor(
                SettingSP.getSingleton(getContext()).getNightMode()
                        ? R.color.content_night
                        : R.color.content_day));
        int fontSize;
        switch (SettingSP.getSingleton(getContext()).getSize()) {
            case SettingSP.TEXT_SIZE_SMALL:
                fontSize = getResources().getDimensionPixelSize(R.dimen.book_font_size_small);
                break;
            case SettingSP.TEXT_SIZE_NORMAL:
                fontSize = getResources().getDimensionPixelSize(R.dimen.book_font_size_normal);
                break;
            case SettingSP.TEXT_SIZE_LARGE:
                fontSize = getResources().getDimensionPixelSize(R.dimen.book_font_size_large);
                break;
            case SettingSP.TEXT_SIZE_EXLARGE:
                fontSize = getResources().getDimensionPixelSize(R.dimen.book_font_size_exlarge);
                break;
            default:
                fontSize = getResources().getDimensionPixelSize(R.dimen.book_font_size_normal);
                break;
        }
        charPaint.setTextSize(fontSize);
        Paint.FontMetrics metrics = charPaint.getFontMetrics();
        this.charHeight = (int) (metrics.descent - metrics.ascent);
        this.lineNum = (height + lineSpace) / (charHeight + lineSpace);

        if (bookPager == null) {
            bookPager = new ViewPager(getContext());
            LayoutParams lp = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
            addView(bookPager, lp);
            bookPager.addOnPageChangeListener(new BookPageChangeListener());
            bookPager.setOnTouchListener(new PagerTouchListener());
        }
        pagerAdapter = new BookPagerAdapter(getContext());
        bookPager.setAdapter(pagerAdapter);
        pagerAdapter.prepare(charPaint, lineNum, lineSpace, charHeight);
    }

    private void processWhatPrepared() {
        callback.onPrepared();
    }

    public int getIndex() {
        return bookPager.getCurrentItem();
    }

    public void setIndex(int i) {
        bookPager.setCurrentItem(i, true);
    }

    public void setIndex(int i, boolean smooth) {
        bookPager.setCurrentItem(i, smooth);
    }

    public void setScrollEnabled(boolean enable) {
        enableScrolling = enable;
    }

    public int getSize() {
        return getPages().size();
    }

    public Page getCurrPage() {
        return getPages().get(getIndex());
    }

    public List<Page> getPages() {
        return pages;
    }

    public boolean isPrepared() {
        return getPages() != null && !getPages().isEmpty();
    }

    public void invalidateNightmode() {
        charPaint.setColor(getContext().getResources().getColor(
                SettingSP.getSingleton(getContext()).getNightMode()
                        ? R.color.content_night
                        : R.color.content_day));
        if (pagerAdapter != null) {
            pagerAdapter.notifyDataSetChanged();
        }
    }

    public void preparedAsync(final Chapter chapter, final List<Paragraph> paragraphs, final ICallback callback) {
        this.chapter = chapter;
        this.callback = callback;

        new AsyncTask<Void, Void, Void>() {

            @Override
            protected void onPreExecute() {
                setupTraditional();
                setupPager();
            }

            @Override
            protected Void doInBackground(Void... params) {
                List<String> lines = new ArrayList<>();
                LogHelper.warn(TAG, "traditional:" + traditional + " " + chapter.getTitle());
                LogHelper.warn(TAG, "translate before:" + paragraphs.get(0).getContent() + " after:" + ConvertUtil.toTraditional(paragraphs.get(0).getContent()));
                for (Paragraph p : paragraphs) {
                    String content = traditional
                            ? ConvertUtil.toTraditional(p.getContent())
                            : p.getContent();

                    if (p.getType() == 1) {
                        lines.add("{{{IMG}}}" + content);
                    } else {
                        content = "　　" + content;
                        while (content.length() > 0) {
                            int offset = charPaint.breakText(content, true, width, null);
                            lines.add(content.substring(0, offset));
                            content = content.substring(offset);
                        }
                    }
                }

                pages = new ArrayList<>();

                int pageStart = 0;
                int pageEnd = 0;
                Page page = new Page(pageStart, pageEnd);
                for (int i = 0; i < lines.size(); i++) {
                    String line = lines.get(i);

                    if (line.startsWith("{{{IMG}}}")) {
                        if (page.getLines() != null && page.getLines().size() > 0) {

                            page.setEnd(pageEnd);
                            pages.add(page);

                            pageStart = pageEnd;
                            page = new Page(pageStart, pageEnd);
                        }

                        page.setType(Page.TYPE_ILLUSTRATION);
                        page.addLine(line.replace("{{{IMG}}}", ""));
                        pageEnd += line.length();

                        page.setEnd(pageEnd);
                        pages.add(page);

                        pageStart = pageEnd;
                        page = new Page(pageStart, pageEnd);
                    } else {
                        page.setType(Page.TYPE_CONTENT);
                        page.addLine(line);
                        pageEnd += line.length();
                    }

                    if (page.getLines() != null && page.getLines().size() > 0 && page.getLines().size() == lineNum) {
                        page.setEnd(pageEnd);
                        pages.add(page);

                        pageStart = pageEnd;
                        page = new Page(pageStart, pageEnd);
                    }
                }

                if (page.getLines() != null && page.getLines().size() > 0) {
                    page.setEnd(pageEnd);
                    pages.add(page);
                }

                chapter.setTotal(pageEnd);

                for (int i = 0; i < pages.size(); i++) {
                    pages.get(i).setIndex(i);
                    LogHelper.warn(TAG, "page:" + i + " start:" + pages.get(i).getStart() + " end:" + pages.get(i).getEnd());
                }
                return null;
            }

            @Override
            protected void onPostExecute(Void aVoid) {
                pagerAdapter.setPagers(pages);
                pagerAdapter.notifyDataSetChanged();
                handler.sendMessage(handler.obtainMessage(WHAT_PREPARED));
            }
        }.execute();
    }

    class BookPageChangeListener extends ViewPager.SimpleOnPageChangeListener {
        @Override
        public void onPageSelected(int position) {
            if (callback != null) {
                callback.onPageChanged();
            }
        }
    }

    class PagerTouchListener implements OnTouchListener {

        @Override
        public boolean onTouch(View v, MotionEvent event) {
            if (enableScrolling) {
                return gestureDetector.onTouchEvent(event);
            } else {
                if (event.getAction() == MotionEvent.ACTION_UP) {
                    callback.onCenterClick();
                }
                return true;
            }
        }
    }

    class GestureDetectorSimpleOnGestureListener extends GestureDetector.SimpleOnGestureListener {

        @Override
        public boolean onDown(MotionEvent e) {
            return false;
        }

        @Override
        public boolean onSingleTapUp(MotionEvent e) {
            float x = e.getX();
            float y = e.getY();

            if (x < width / 3 || (y < height / 3 && x < width * 2 / 3)) {
                callback.onPrevClick();
            } else if (x > width * 2 / 3 || (y > height * 2 / 3 && x > width / 3)) {
                callback.onNextClick();
            } else {
                callback.onCenterClick();
            }

            return true;
        }

        public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
            return false;
        }

        @Override
        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
            return false;
        }

        @Override
        public boolean onSingleTapConfirmed(MotionEvent e) {
            return false;
        }
    }

    class BookPagerAdapter extends PagerAdapter {
        private Context context;
        private List<Page> pages;

        private Paint charPaint;
        private int lineNum;
        private int lineSpace;
        private int charHeight;

        public BookPagerAdapter(Context context) {
            this.context = context;
        }

        public void setPagers(List<Page> pages) {
            this.pages = pages;
        }

        public void prepare(Paint charPaint, int lineNum, int lineSpace, int charHeight) {
            this.charPaint = charPaint;
            this.lineNum = lineNum;
            this.lineSpace = lineSpace;
            this.charHeight = charHeight;
        }

        @Override
        public void destroyItem(ViewGroup container, int position, Object object) {
            if (object != null && object instanceof View) {
                container.removeView((View) object);
            }
        }


        @Override
        public Object instantiateItem(ViewGroup container, int position) {
            Page page = pages.get(position);
            View nextView;
            if (page.getType() == Page.TYPE_ILLUSTRATION) {
                nextView = new QingIllustrationView(context).prepare(page);
            } else {
                nextView = new ContentView(context).prepare(page, charPaint, lineNum, lineSpace, charHeight);
            }
            container.addView(nextView);
            nextView.postInvalidate();
            return nextView;
        }

        @Override
        public int getCount() {
            return pages == null ? 0 : pages.size();
        }

        @Override
        public boolean isViewFromObject(View arg0, Object arg1) {
            return arg0 == arg1;
        }

        @Override
        public int getItemPosition(Object object) {
            return POSITION_NONE;
        }
    }

}
